package map.abstractor.xmlmodel;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import map.tools.interactions.EscapeChars;

import org.w3c.dom.Element;

/**
 * Abstract Class XMLObject Represent any XML element for LAIM language
 */
public abstract class XMLObject {
	/**
	 * Constants
	 */
	private static int currentId = 0;

	/**
	 * Fields	
	 */
	private ArrayList<XMLObject> childs;
	private Map<String, StringBuffer> attributes;
	private String tagName;//Name
	private String content;
	private boolean withId;
	private boolean withLayoutComm;
	private String commLayout;
	private boolean withStyleComm;
	private String commStyle;

	/**
	 * Constructor
	 * 
	 * @param tagName :
	 *            Xml element tag
	 * @param id :
	 *            true if the element need an id, false else
	 */
	public XMLObject(String tagName, boolean id, boolean withLayout,
			boolean withStyle) {
		childs = new ArrayList<XMLObject>();
		attributes = new HashMap<String, StringBuffer>();
		this.tagName = tagName;
		this.content = null;
		this.withId = id;
		this.withLayoutComm = withLayout;
		this.withStyleComm = withStyle;
		this.commLayout = "";
		this.commStyle = "";
		if (withId)
			this.addAttribute("id", new StringBuffer().append(this.getTagName() + (currentId++)));
	}

	/**
	 * build Attributes
	 * 
	 * @param n :
	 *            a FlexElement
	 * @param sens :
	 *            translation attributes map
	 */
	public void build(Element n, Map<String, String> sens) {
		// Set Other Attributes
		if (sens != null)
			for (String attr : sens.keySet())
				if (n.getAttribute(attr) != null)
					this.addAttribute(sens.get(attr), new StringBuffer().append(n.getAttribute(attr)));
	}

	/**
	 * addAttribute
	 * 
	 * @param name :
	 *            String key
	 * @param value :
	 *            String value
	 */
	public void addAttribute(String name, StringBuffer value) {
		attributes.put(name, value);
	}

	/**
	 * getTagName
	 * 
	 * @return : String represents Xml element.
	 */
	public String getTagName() {
		return tagName;
	}

	/**
	 * getContent
	 * 
	 * @return : String represents the content of Xml element.
	 */
	public String getContent() {
		return content;
	}

	/**
	 * toString
	 * 
	 * @return : StringBuffer, Xml File
	 */
	public String toString() {
		return toString("").toString();
	}

	/**
	 * toString
	 * 
	 * @return : StringBuffer, Xml File
	 */
	public StringBuffer toString(int s) {
		return toString("");
	}

	/**
	 * getChilds
	 * 
	 * @return ArrayList<XMLObject> all childs elements
	 */
	public ArrayList<XMLObject> getChilds() {
		return childs;
	}

	/**
	 * getAttribute
	 * 
	 * @param key :
	 *            the attribute key
	 * @return the value of the attribute for key, null if not exist
	 */
	public StringBuffer getAttribute(String key) {
		return attributes.get(key);
	}

	/**
	 * addChild
	 * 
	 * @param e :
	 *            XMLObject
	 */
	public void addChild(XMLObject e) {
		this.childs.add(e);
	}

	/** **************************************************************** */

	protected StringBuffer toString(String indent) {
		StringBuffer  res =new StringBuffer();
		res.append(indent + "<" + getTagName());
		for (String key : attributes.keySet())
		{	
			res.append( " " + key + "=\"" +EscapeChars.forXML(attributes.get(key).toString()) + "\"");
		
		}
		if ( this.childs.isEmpty() && 
				content == null && 
				(commLayout.length() == 0) &&
				(commStyle.length() == 0))
			res.append( " />\n");
		else {
			res.append( " >\n");
			if (this.withLayoutComm && (commLayout.length() != 0))
				res.append( indent + "\t<!-- Layout : " + commLayout + " -->\n");
			if (this.withStyleComm && (commStyle.length() != 0))
				res.append( indent + "\t<!-- Style : " + commStyle + " -->\n");
			if (content != null)
				res.append( indent + "\t" + content + "\n");

			for (XMLObject e : childs)
				res.append( e.toString(indent + "\t"));
				res.append( indent + "</" + getTagName() + ">\n");
		}
		return res;
	}

	protected void setContent(String content) {
		this.content = content;
	}

}
